<?php

/**
 * Connect redis 
 * Author : phuongtn
 */
class Fpt_Caching_Redis
{

    /**
     * Hold all instances
     * @var <array>
     */
    private static $_instances = array();
    /**
     * Hold all related keys in this instance
     * @var <array>
     */
    private static $_keys = array();
    
    private static $_conf = array();
    /**
     * Default total db of 1 instance redis 
     */
    const TOTAL_DB = 256;
    /**
     * Constructor of class
     * we don't permit an explicit call of the constructor! (like $v = new Singleton())
     */
    protected function __construct($fullIdc)
    {
        $conf = self::$_conf[$fullIdc];
        $this->_redis = Fpt_Nosql::getInstance($conf); 

    }
    /**
     * Get redis instance by module, instance(idc) [, shardingId]
     * @param string $module module where cache ini file is stored
     * @param string $instance idc for redis
     * @param int $shardingID sharding
     * @return Fpt_Nosql 
     */
    public static function getInstance($module, $instance, $shardingID = 0)
    {
        try
        {
            //get redis conf by module & idc
            $redisConf  = Fpt_Global::getConfig('application');
          
            $config     = $redisConf['nosql'][$instance];            
            self::$_keys = Fpt_Global::getConfig('caching');  
            //count total db
            $totalDB = count($config);
            //default sharding db
            $shardingDB = 0;
            //check if have to sharding
            if($totalDB > 1)
            {
                //get sharding db from fw
                $shardingDB = (!empty($shardingID))? Fpt_Sharding::getTableByID($shardingID, $totalDB):0;
            }

            //init idc full
            $idcFull = $instance.$shardingDB;
            
            if (empty(self::$_instances[$module . '_' . $instance]))
            {
                self::$_conf[$module . '_' . $idcFull] = $config[$shardingDB];
                self::$_instances[$module . '_' . $idcFull] = new self($module . '_' . $idcFull);           
            }

            return self::$_instances[$module . '_' . $idcFull];
        }
        catch(Exception $ex)
        {
            throw new Core_Exception($ex->getMessage(), $ex->getCode());
        }
    }
    
    /**
     * Get slot of db redis
     * @param <string> $key
     * @return <string>
     */
    public static function getSlotRedisID($key)
    {
        return Fpt_Sharding::getTableRedisByID($key, self::TOTAL_DB);
    }

    /**
     * get redis storage: can use for transaction/pineline
     * @param int $sharding_id
     * @return type 
     */
    public function getRedisStorage($sharding_id, $slot_redis = null)
    {
        if(!is_null($this->_redis))
        {
            if(is_null($slot_redis))
            {
                //call static function to get slot redis by sharding id
                $slotRedis = Fpt_Caching_Redis::getSlotRedisID($sharding_id);
            }
           
            //select redis db
            $this->_redis->selectDb($slotRedis);
            //return redis storage
            return $this->_redis->getStorage();
        }
        return false;
    }

    /**
     * Make redis key
     * @param string $cache_key
     * @param array $args
     * @return string cache key 
     */
    public static function makeRedisKey($cache_key, $args)
    {
        //get redis conf by module & idc
        $config = self::$_keys;
        //get prefix caching from config by key
        $format = $config[$cache_key];
        //valid key
        if($format != '')
        {
            if (!is_array($args))
            {
                return sprintf($format, $args);
            }
            $format = array($format);
            $args   = array_merge($format, $args);
            return call_user_func_array("sprintf", $args);
        }
        return false;
    }
    
    public static function removeKeyPrefix(&$item, $key, $prefixConf)
    {
        //get redis conf by module & idc
        $config = self::$_keys;
        //get prefix caching from config by key
        $format = $config[$prefixConf];
        $prefix = str_replace('%s', '', $format);
        $item = str_replace($prefix, '', $item);
        $item = str_replace(':', '', $item);
    }
}
